/*  
    This file is part of the Arctic Fox Code Tree (AFCT).
    Copyright 2002, Arctic Fox Computer Consulting Inc.

    AFCT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    AFCT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with AFCT; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


package org.afox.util.validators;

/**
   <P> This is an abstract class which defines the Validator framework.  It is based upon the
   chain of responsibility pattern.  Each node within the chain performs some basic form
   of validation upon the specified TARGET object.  If the TARGET validates correctly, the
   target is passed to the next node in the chain.  If the TARGET validation fails, a ValidateException
   is thrown.  

   <P> Complex validation rules can be constructed from simple validators.  Just remember for a target
   to be valid, it must pass the validation test for EACH node.

   <P> It is recommended that complex Validators be used in conjunction with Abstract Factory Objects.
   By using Abstract Factories, one can centralize validation rules thus improving the consistency
   of application for those rules.  To improve performance (at a slight cost of memory usage), the
   Abstract Factory can cache Validators
*/

public abstract class Validator
{
	private Validator next = null;
	private String errorMessage = null;

/** Default Validator */
	public Validator()
	{
		super();
	}

/** This constructor takes a reference to the previous validator in the chain.  The previous object
    is notified that this object is the next in the chain.
*/
	public Validator(Validator previous)
	{
		super();
		if (previous!=null)
			previous.setNext(this);
	}

/** This constructor offers the ability to provide an Error message which is reported in the event
    that the validation fails.  This error message will override the standard error message for the
    validator
*/
	public Validator(String anErrorMessage)
	{
		super();
		if (errorMessage!=null)
			errorMessage = anErrorMessage;
	}

/** This constructor allows for previous and error message parameters */
	public Validator(Validator previous, String anErrorMessage)
	{
		super();
		if (previous!=null)
			previous.setNext(this);
		if (errorMessage!=null)
			errorMessage = anErrorMessage;
	}

	private void setNext(Validator nextValidator)
	{
		next = nextValidator;
	}

/** If error message has been set, it will be returned.  If not, this method will simply return the
    default error message which has been passed into this method */
	public String getErrorMessage(String defaultErrorMessage)
	{
		if (errorMessage == null)
			return defaultErrorMessage;
		else
			return errorMessage;
	}


/** To validate a TARGET object, invoke this method.  If the validation chain does not validate
    the TARGET, a ValidateException will be thrown.  If the TARGET object is null, an 
    IllegalArgumentException will be thrown.  
*/
	public void validate(Object theTarget) throws ValidateException
	{
		// Throw exception if object to be validated is null
		if (theTarget==null)
			throw new IllegalArgumentException("Null validation object specified");

		// perform the validation
		validateImpl(theTarget);

		//  Pass validation on to next in chain.
		if (next!=null)
			next.validate(theTarget);
	}

/** This is the implementation method for a specific validation.  All Validators must override
    this method.  This method should return normally if the TARGET parameter validates correctly.
    The method should throw a ValidateException (with appropriate error message) if the TARGET
    does not pass the validation rule.
*/
	protected abstract void validateImpl(Object theParameter) throws ValidateException;

/** This method produces a string which contains human readible text which describes the validator chain. */

	public String toString()
	{
		if (next!=null)
			return getDescription() + "\n" + next.toString();
		else
			return getDescription() + "\n";
	}

/** This method returns a human readible string which describes the validator.  
    All validators must provide an implementation for this method.
 */
	protected abstract String getDescription();


}

